#ifndef _AME_MAP_H_
#define _AME_MAP_H_

#define MAP(i) ((struct world_map *)s.maps[i].p)
//#define CELL(map, y, x) ((struct world_cell*)(map->cells[y][x]))
#define CELL(a) ((struct world_cell *)a)
#define DISTANCE(x0, y0, x1, y1) (int)(abs(x0-x1) > abs(y0-y1) ? abs(x0-x1) : abs(y0-y1))
#define DISTANCEC(cell0, cell1) (int)(abs(cell0->X-cell1->X) > abs(cell0->Y-cell1->Y) ? abs(cell0->X-cell1->X) : abs(cell0->Y-cell1->Y))
#define MAX_OBJECTS_IN_CELL 9

#define MAP_MAX_HEIGHT 150
#define MAP_MAX_WIDTH 150
#define MAP_MAX_OBJECTS 1024
#define MAP_WOS_MAX_SIZE 9
#define MAP_MAX_NAME 16
#define MAP_MAX_MOBS 16
#define MAP_MAX_ITEMS 16
#define MAP_MAX_CHARS 16
#define MAP_MAX_OBJECTS_IN_CELL 16

#ifndef MAX_CHAR_NAME
#define MAX_CHAR_NAME 24
#endif

typedef enum {
 W_NULL = 0,
	W_MAP = 1,
	W_CELL = 2,
	W_OBJECT = 3,
	W_CHAR = 4,
	W_MOB = 5,
	W_UNKNOWN = 6
} WorldData;

enum WorldActionType {
	WAT_ATTACK,
	WAT_WALK,
	WAT_NONE
};

typedef enum {
		WO_NONE = 0,
		WO_CHAR = 1,
		WO_MOB = 2,
		WO_ITEM = 3,
		WO_AE = 4
} WorldObject;

struct world_object {
	unsigned id: 32;
	WorldObject type;
	struct chain_node *map_node;
	struct chain_node *cell_node;
	struct world_cell *cell;
	void *object;
};


struct world_item {
	struct cell *cell;
	int id;
};

/* hello
struct world_node {
	int id;
	struct world_cell *cell;
	struct world_cell *target;
	struct chain_node *cellnode;
	void *val;
};
*/

struct world_cell {
	struct world_map *wmap;
	unsigned map_id: 8;
	unsigned X: 8;
	unsigned Y: 8;
	unsigned passable: 1;
	unsigned exists: 1;
	struct chain_set *objects;
};

struct world_map {
	unsigned map_id: 8;
  char name[MAP_MAX_NAME];
	struct world_cell *cells[MAP_MAX_HEIGHT][MAP_MAX_WIDTH];
	unsigned width: 8;
	unsigned height: 8;
	struct chain_set *items;
	struct chain_set *chars;
	struct chain_set *mobs;
};

struct world_object_selection {
	struct world_object **objects;
	int size;
};

void *map_init(unsigned int, const char *, const char *);
void  map_shut();

struct world_object_selection *map_initWOS(int);
int map_addToWOS (struct world_object_selection *, struct world_object *);
int map_reallocWOS(struct world_object_selection *me, int size);
void map_shutWOS (struct world_object_selection *);
void map_addObject(struct world_map *, struct world_object *);

int map_selectInCell(struct world_cell *, struct world_object_selection *);
int map_selectInRadius(struct chain_set *, struct world_cell *, unsigned short, unsigned int);

#endif
